﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace Derbster.Domain
{
    [ContractClass(typeof(MatchRepositoryContracts))]
    public interface IMatchRepository : IDisposable, IQueryable<Match>
    {
        Match Create(bool isRegulation, bool isSanctioned, Roster firstTeamRoster, Roster secondTeamRoster, string name);
        Match Create(
            bool isRegulation,
            bool isSanctioned,
            Roster firstTeamRoster,
            Roster secondTeamRoster,
            string name,
            string location);
        Match Create(
            bool isRegulation,
            bool isSanctioned,
            Roster firstTeamRoster,
            Roster secondTeamRoster,
            string name,
            string location,
            DateTime? when);
      
        Match FindById(int id);
        Match FindByGlobalIdentifier(Guid globalGuid);
        Match FindByName(string name);
        IEnumerable<Match> FindByDate(DateTime fromDate, DateTime toDate);
        IEnumerable<Match> FindByLocation(string location);

        Match Update(Match match);
        void Delete(Match match);
    }

    [ContractClassFor(typeof(IMatchRepository))]
    public abstract class MatchRepositoryContracts : IMatchRepository
    {
        public void Dispose()
        {
            throw new NotImplementedException();
        }

        public IEnumerator<Match> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public Expression Expression
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public Type ElementType
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public IQueryProvider Provider
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public Match Create(bool isRegulation, bool isSanctioned, Roster firstTeamRoster, Roster secondTeamRoster, string name)
        {
            Contract.Requires(firstTeamRoster != null);
            Contract.Requires(secondTeamRoster != null);
            Contract.Requires((isSanctioned && isRegulation) || (!isSanctioned));
            Contract.Requires(!String.IsNullOrWhiteSpace(name));
            Contract.Ensures(Contract.Result<Match>().MatchId > 0);
            return null;
        }

        public Match Create(
            bool isRegulation,
            bool isSanctioned,
            Roster firstTeamRoster,
            Roster secondTeamRoster,
            string name,
            string location)
        {
            Contract.Requires(firstTeamRoster != null);
            Contract.Requires(secondTeamRoster != null);
            Contract.Requires((isSanctioned && isRegulation) || (!isSanctioned));
            Contract.Requires(!String.IsNullOrWhiteSpace(name));
            Contract.Requires(!String.IsNullOrWhiteSpace(location));
            Contract.Ensures(Contract.Result<Match>().MatchId > 0);
            return null;
        }

        public Match Create(
            bool isRegulation,
            bool isSanctioned,
            Roster firstTeamRoster,
            Roster secondTeamRoster,
            string name,
            string location,
            DateTime? when)
        {
            Contract.Requires(firstTeamRoster != null);
            Contract.Requires(secondTeamRoster != null);
            Contract.Requires((isSanctioned && isRegulation) || (!isSanctioned));
            Contract.Requires(!String.IsNullOrWhiteSpace(name));
            Contract.Requires(!String.IsNullOrWhiteSpace(location));
            Contract.Ensures(Contract.Result<Match>().MatchId > 0);
            return null;
        }

        public Match FindById(int id)
        {
            Contract.Requires(id > 0);
            return null;
        }

        public Match FindByGlobalIdentifier(Guid globalId)
        {
            Contract.Requires(globalId != Guid.Empty);
            return null;
        }

        public Match FindByName(string name)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(name));
            return null;
        }

        public IEnumerable<Match> FindByDate(DateTime fromDate, DateTime toDate)
        {
            Contract.Requires(fromDate <= toDate);
            return null;
        }

        public IEnumerable<Match> FindByLocation(string location)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(location));
            return null;
        }

        public Match Update(Match match)
        {
            Contract.Requires(match != null);
            Contract.Requires(match.MatchId > 0);
            return null;
        }

        public void Delete(Match match)
        {
            Contract.Requires(match != null);
            Contract.Requires(match.MatchId > 0);
        }
    }
}
